<?php

class LightConn_mysql extends LightConnDriver 
{
	/**
	 * Objeto de conexão
	 *
	 * @var mysqli
	 */
	protected $conn;
	
	/**
	 * Resultado da consulta
	 *
	 * @var mysqli_result
	 */
	protected $resultSet;
	
	/*
	* Configura se retorna apenas uma linha;
	*/
	protected $oneLine;
	
	
	/**
	 * Nova conexão com o banco
	 *
	 * @param string $host
	 * @param string $user
	 * @param string $password
	 * @param string $schema
	 * @return bool
	 */
	public function Connect($host, $user, $password, $database = null, $persistente = true)
	{
		if($persistente)
			@$this->conn = mysql_pconnect($host, $user, $password);
		else
			@$this->conn = mysql_connect($host, $user, $password);
		
        if (!($this->conn === false)) 
        {
        	if($database)
        	{
        		$this->Query('SET NAMES UTF8');        		
		        if (mysql_select_db($database, $this->conn) === false) 
		        {
		            throw new LightConnException("Erro ao conectar no banco da dados em $host com usuário $user.", mysql_error($this->conn),  mysql_errno($this->conn));
		        }
        	}      	 
        }
        else
        {
        	throw new LightConnException("Erro ao conectar no banco da dados em $host com usuário $user.", null,  null);
        }
		return true;
	}	
	
	
	/**
	 * Fechar conexão com o banco
	 *
	 */
	public function Disconnect()
	{
		mysql_close($this->conn);
		$this->conn = null;
	}
	
	/**
	 * Executa um query SQL e retorna o número de linhas afetada[.
	 *
	 * @param string $sql
	 * @param array $prepare
	 * @return int
	 */
	public function Execute($sql, $prepare = null)
	{
		$this->query = $sql;
		$this->prepare = $prepare;
		$this->resultSet = null;

		$sql = $this->VirtualPrepare($sql, $prepare);		
		$this->query = $sql;
			
		$this->resultSet = mysql_query($sql,$this->conn);
		
		if (!$this->resultSet)
		{			
			$this->Error("Não foi possível executar a query.");
		}
		
		return mysql_affected_rows();
	}
	
	/**
	 *
	 * @param string $sql
	 * @param array $prepare
	 * @return string
	 */
	public function VirtualPrepare($sql, $prepare)
	{
		$newSql = '';
		$arrPlaces = explode('?', $sql);
		
		$end = array_pop($arrPlaces);
		
		$i = $j = 0;
		foreach ($arrPlaces as $index => $place)
		{
			$newSql .= $arrPlaces[$j] . "'" . $prepare[$i] . "'";
			$i++;
			$j++;
		}
		if ($newSql)
		{
			return $newSql . $end;
		}
		return $sql;
	}
	
	/**
	 * Executa um query SQL
	 *
	 * @param string $sql
	 * @param array $prepare
	 * @return LightConnIterator
	 */
	public function Query($sql, $prepare = null , $oneLine = false)
	{	
		
		if($this->Execute($sql, $prepare) > -1)
		{
			return new LightConnIterator_mysql($this->resultSet, $this , $oneLine);
		}
		
		return new LightConnIterator_mysql($this->resultSet, $this , $oneLine);
	}
	
	/**
	 * Tratamento de erros
	 *
	 * @param string $message
	 * @param link $source
	 * @return bool
	 */
	public function Error($message = null, $source = null, $force = false)
	{
		throw new LightConnException($message, $this->conn->error, $this->conn->errno, $this->query);
		
	}
	
	public function Begin()
	{
		$null = mysqli_query($this->conn, "START TRANSACTION");
		return mysqli_query($this->conn, "BEGIN");
	}

	public function Commit()
	{
		return mysqli_query($this->conn, "COMMIT");
	}
	
	public function Rollback()
	{
		return mysqli_query($this->conn, "ROLLBACK");
	}
	
	/**
	 * Importar um arquivo SQL
	 *
	 * @param string $file
	 * @return bool
	 */
	public function Import($file)
	{
		return $this->ImportSQL(file_get_contents($file));
	}
	
	public function LastInsertId()
	{
		return mysql_insert_id($this->conn);
	}
	
	
	/**
	 * Importar um arquivo SQL
	 *
	 * @param string $sql
	 * @return bool
	 */
	public function ImportSQL($sql)
	{
		$arrLines = explode("\n", $sql);
		
		$this->Begin();
		
		$query = "";
		
		try {
			
			
			$hasDelimiter = false;
			foreach ($arrLines as $line)
			{
				if(preg_match('#DELIMITER\s+(^[;].+|;{2,}?)#', $line, $arrMatch))
				{
					$hasDelimiter = true;
					$delimiter = $arrMatch[1];
					$delimiter = preg_replace('#\$|\/|\|#', '\\\\\0', $delimiter);
//					$this->conn->Execute($line);
					$query = '';
					continue;
				}
				else
				{
					if(preg_match('#DELIMITER\s*(;{1})#', $line))
					{
						$hasDelim = false;
						if ($query)
						{
							$this->Execute($line);
						}
						$query = '';
						continue;
					}
				}
				$tsl = trim($line);
				if (($tsl != "") && (substr($tsl, 0, 2) != "--") && (substr($tsl, 0, 1) != "#"))
				{
					$query .= $line;
					
					if(preg_match("/;\s*$/", $line) && !$hasDelimiter)
					{
						$query = str_replace(";", "", "$query");
						$this->Execute($query);
						$query = "";
					}
					else
					{
						if ($hasDelimiter && preg_match('#' . $delimiter . '\s*$#', $line))
						{
							$query = preg_replace('/' . $delimiter . '\s*$/', "", $query);
							$this->Execute($query);
							$query = "";
						}
					}
				}
			}
		}
		catch (Exception $ex)
		{
			$this->Rollback();
			throw $ex;
		}
		
		$this->Commit();
	}
	
	/**
	 * Retorna o driver nativo
	 *
	 * @return mysqli
	 */
	public function getDriver()
	{
		return $this->conn;
	}
}

class LightConnIterator_mysql extends LightConnIterator
{
	/**
	 * Objeto de conexão
	 *
	 * @var mysqli
	 */
	protected $conn;
	
	protected $oneLine;
	/**
	 * Recebe um mysqli_result ou mysqli_stmt
	 *
	 * @param mysql_result $result
	 * @param LightConn_mysql
	 * @return LightConnIterator_mysql
	 */
	public function LightConnIterator_mysql($result , $driver, $oneLine)
	{	
		if(!is_bool($result))
			$this->total = mysql_num_rows($result);
				
		$this->result = $result;
		$this->driver = $driver;	
		$this->oneLine = $oneLine;		
		$this->current = 0;		
	}
	
	/**
	 * Retorna um array associativo com os campos do registro atual
	 * 
	 * $arr['nome_campo'] -> valor do campo
	 *
	 * @return array
	 */
	protected function Fetch()
	{
		if ($this->result)
		{
			$this->arrFields = mysql_fetch_assoc($this->result);
		}		
		return $this->arrFields;
	}
	
	/**
	 * Liberar consulta da memória
	 *
	 */
	protected function FreeResult()
	{
		//mysql_free_result($this->result);
	}
	
	/**
	 * Monta um array com os campos da consulta
	 *
	 * @param result $result
	 * @return array
	 */
	public function BindFields()
	{
		$arrFieldControl = array();
		
		while ($field = mysql_fetch_field($this->result))
		{
			$name = trim($field->name);
			if ($arrFieldControl[$name])
			{
				$name = $name . ($arrFieldControl[$name] + 1);
			}
			$arrFields[$name] = $name;
			$arrFieldControl[$name]++;
		}
		
		return $arrFields;
	}
	
	
	/**
	 * Retorna Consulta em um Objeto Array
	 *
	 * @param result $result
	 * @return array
	 */
	public function ResultArray()
	{
		
		if(!is_bool($this->result))
		{
			$arrResult = array();
			if($this->oneLine == true)
			{		
				$arrResult	= mysql_fetch_assoc($this->result);
				
			}else
			{
				while ($row = mysql_fetch_assoc($this->result)) {
				   $arrResult[] = $row;
				}
			}
			return $arrResult;
		}
		else
		{
			return $this->result;
		}		
	}
	
	/**
	 * Retorna todos os campos da consulta num array
	 * 
	 * Ex: $arr[0]; -> campo1
	 *
	 * @return array
	 */
	public function Fields()
	{
		if (!$this->arrFields)
		{
			$this->arrFields = $this->BindFields($this->result);
		}
		return array_keys($this->arrFields);
	}
}
?>